#include "StdAfx.h"
#include "Number.h"
#include <memory.h>
#include <math.h>


#if ( NORMAL_MODE )

Number::Number( relative_type dec )
{
	m_decimal = dec;
	memset( &m_binary, 0, sizeof( m_binary ) );

	ConvertBinary( dec );
}


Number::Number( int* bin )
{
	m_decimal = 0;
	memcpy( m_binary, bin, sizeof( m_binary ) );

	ConvertDecimal( bin );
}


Number::~Number( void )
{
}


void Number::ConvertBinary( relative_type dec )
{
	relative_type mask = 1 << ( MAX_BIT_SIZE - 1 );

	for( relative_type i = 0; i < MAX_BIT_SIZE; ++i )
	{
		m_binary[i] = ( 0 != ( dec & mask ) );
		mask >>= 1;
	}
}


void Number::ConvertDecimal( int* bin )
{
	for( int i = 0; i < MAX_BIT_SIZE; ++i )
	{
		if( bin[i] )
		{
			m_decimal += (relative_type)pow( (long double)2, ( MAX_BIT_SIZE - ( i + 1 ) ) );
		}
	}
}

#else

Number::Number( std::string val, NumberType::Enum number_type )
{
	switch( number_type )
	{
	case NumberType::Binary :
		{			
			m_binary = val.substr( FindFirst( val ), val.size() - FindFirst( val ) );
			ConvertDecimal( val );
		}
		break;

	case NumberType::Decimal :
		{
			m_decimal = val;
			ConvertBinary( val );
		}
		break;
	}	
}


Number::~Number( void )
{
}


void Number::ConvertBinary( std::string dec )
{
	std::string quotient;
	std::ostringstream ostr;

	bool next = false;


	for( size_t i = 0; i < dec.size(); ++i )
	{
		std::string pop( dec.substr( i, 1 ).c_str() );

		if( !next && 2 > atoi( pop.c_str() ) )
		{
			next = true;
			quotient = pop;

			continue;
		}

		if( next )
		{
			pop.insert( 0, quotient );

			std::ostringstream ostr;
			ostr << atoi( pop.c_str() ) / 2;

			quotient.assign( ostr.str().c_str() );
			quotient.append( dec.substr( i, dec.size() - ( i + 1 ) ) );

			next = false;
		}
		else
		{
			std::ostringstream ostr;
			ostr << atoi( pop.c_str() ) / 2;

			quotient.assign( ostr.str().c_str() );
			quotient.append( dec.substr( i, dec.size() - ( i + 1 ) ) );
		}

		pop = dec.substr( dec.size() - 1, 1 );
		ostr << atoi( pop.c_str() ) % 2;

		m_binary.insert( 0, ostr.str().c_str() );

		break;
	}


	switch( atoi( quotient.c_str() ) )
	{
	case 0 :
		return;

	case 1 :		
		ostr << atoi( quotient.c_str() );
		m_binary.insert( 0, ostr.str().c_str() );
		break;

	default :
		ConvertBinary( quotient );
		break;
	}
}


void Number::ConvertDecimal( std::string bin )
{
	long double pos = 0;

	for( size_t i = bin.size(); i > 0; --i )
	{
		std::ostringstream ostr;
		std::string pop( bin.substr( i - 1, 1 ) );

		if( atoi( pop.c_str() ) )
		{
			ostr << (long double)pow( (long double)atoi( pop.c_str() ), pos );
			m_decimal.append( ostr.str().c_str() );
		}

		++pos;
	}
}


size_t Number::FindFirst( std::string src )
{
	for( size_t first = 0; first < src.size(); ++first )
	{
		if( "1" == std::string( src.substr( first, 1 ) ) )
		{
			return first;
		}
	}

	return 0;
}

#endif
